package security;

import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;

import org.bouncycastle.util.encoders.Base64;

import util.KeyReader;

/**
 * Provides useful methods for timestamp-based security.
 * 
 * @author Lukas
 *
 */
public class TimestampUtil {
	/**
	 * Creates a signature to the given string.
	 * @param s The string.
	 * @return The signature.
	 * @throws IOException
	 */
	public static String getSignature(String s, String user) throws IOException {
		try {
			Signature sig = Signature.getInstance("SHA512withRSA");
			PrivateKey priKey = KeyReader.getInstance().readPrivateKey(true, user);
			sig.initSign(priKey);
			sig.update(s.getBytes());
			return new String(Base64.encode(sig.sign()));
		} catch (NoSuchAlgorithmException e) {
			throw new IOException(e);
		} catch (GeneralSecurityException e) {
			throw new IOException(e);
		}
	}
	
	private static boolean verifySignature(String s, String signature, String user) throws IOException {
		try {
			Signature sig = Signature.getInstance("SHA512withRSA");
			KeyReader kr = KeyReader.getInstance();
			PublicKey pubKey = kr.readPublicKey(user);
			sig.initVerify(pubKey);
			sig.update(s.getBytes());
			return sig.verify(Base64.decode(signature));
		} catch (NoSuchAlgorithmException e) {
			throw new IOException(e);
		} catch (GeneralSecurityException e) {
			throw new IOException(e);
		}
	}
	
	/**
	 * Calculates the timestamp and verifies the signatures.
	 * @param auctionId The id of the auction.
	 * @param price The price.
	 * @param sign An array of the signs attached to the !signedBid message.
	 * @return The timestamp, or 0 if there was an error in verifying the signature.
	 * @throws IOException
	 */
	public static long getTimestamp(String auctionId, String price, String[] sign) throws IOException {
		long timestamp = 0l;
		for (String sig : sign) {
			String[] cmd = sig.split(":");
			if (cmd.length != 3) {
				throw new IOException();
			}
			String s = "!timestamp " + auctionId + ' ' + price + ' ' + cmd[1];
			if (!verifySignature(s, cmd[2], cmd[0])) {
				return 0l;
			}
			timestamp += Long.parseLong(cmd[1]) / sign.length;
		}
		return timestamp;
	}
}
